<?php
/**
 * Model mapper for project builds.
 *
 * @category PhpCilux
 * @package  PhpCilux
 */

/**
 * Model mapper for project builds.
 *
 * @package PhpCilux
 */
class Model_BuildMapper
{

    /**
     * The build dir.
     *
     * @var string
     */
    protected $_buildDir;

    /**
     * The report dirname.
     *
     * @var string
     */
    protected $_reportDir = 'reports';

    /**
     * Hold the builds.
     *
     * @var array
     */
    protected $_builds;

    /**
     * Holds an instance of the class.
     *
     * @var Model_BuildMapper
     */
    protected static $_instance;

    /**
     * Singleton Getter.
     *
     * @param Model_BuildMapper|string $instance Alternative instance.
     *
     * @return Model_BuildMapper
     */
    public static function getInstance($instance = null)
    {
        if ($instance instanceof Model_BuildMapper) {
            self::$_instance = $instance;
        } elseif (null !== $instance) {
            self::$_instance = null;
        }

        if (empty(self::$_instance)) {
            self::$_instance = new self();
        }

        return self::$_instance;
    }

    /**
     * Clone.
     *
     * @return void
     */
    private final function __clone()
    {
    }

    /**
     * Constructor.
     */
    protected function __construct()
    {
        $this->_buildDir = APPLICATION_PATH  . DIRECTORY_SEPARATOR .
                            '..' . DIRECTORY_SEPARATOR .
                            'data' . DIRECTORY_SEPARATOR .
                            'build' . DIRECTORY_SEPARATOR;
    }

    /**
     * Load the builds of the given project.
     *
     * @param string $projectId The project key.
     *
     * @return void
     */
    protected function _loadBuilds($projectId)
    {
        $dir = $this->_buildDir .
               $projectId . DIRECTORY_SEPARATOR .
               $this->_reportDir . DIRECTORY_SEPARATOR;

        if (!is_dir($dir)) {
            $this->_builds[$projectId] = array();
            return;
        }

        if (!empty($this->_builds[$projectId])) {
            return;
        }

        $files = scandir($dir);
        rsort($files);

        $this->_builds[$projectId] = array();
        while (list(,$file) = each($files)) {
            if (!in_array($file, array('..', '.')) && is_dir($dir . $file)) {
                $model = new Model_Build(array('projectKey' => $projectId, 'buildKey' => $file));

                $this->_builds[$projectId][$file] = $model;
            }
        }
    }

    /**
     * Get the last build of the given project.
     *
     * @param string $projectId The project key.
     *
     * @return Model_Build
     */
    public function getLast($projectId)
    {
        $this->_loadBuilds($projectId);

        reset($this->_builds[$projectId]);
        while (list(,$build) = each($this->_builds[$projectId])) {
            return $build;
        }
    }

    /**
     * Get the previous builds.
     *
     * @param string $projectId The project key.
     * @param string $buildId   The build key.
     *
     * @return Model_Build
     */
    public function getBuild($projectId, $buildId)
    {
        $this->_loadBuilds($projectId);

        if (isset($this->_builds[$projectId][$buildId])) {
            return $this->_builds[$projectId][$buildId];
        }
    }

    /**
     * Get the previous builds.
     *
     * @param string  $projectId The project key.
     * @param string  $buildId   The build key.
     * @param integer $limit     Max count of wanted objects.
     *
     * @return array Array og Model_Build.
     */
    public function getPrevBuilds($projectId, $buildId, $limit)
    {
        $this->_loadBuilds($projectId);

        if (!array_key_exists($buildId, $this->_builds[$projectId])) {
            return array();
        }

        $searchPos = array_search($buildId, array_keys($this->_builds[$projectId]));

        return array_slice($this->_builds[$projectId], ($searchPos + 1), $limit);
    }

}